//: Playground - noun: a place where people can play

import UIKit

/// 定义一个类
class Shape {

    // 属性
    var numberOfSides = 0;
    
    // 实力方法
    func simpleDescription() -> String {
        
        return "A shape with \(numberOfSides) sides."
    }
    
    // 类方法
    class func shapeDescription() -> String {
        
        return "我是一个定义形状的类";
    }
}


/// 初始化
class NameShape {

    var numberOfSides: Int = 0;
    var name: String;
    
    
    // 注意初始化前面没有func
    init(name: String) {
        
        self.name = name;
    }
}


/// 继承
class Square: NameShape {

    var sideLength: Double
    
    init(sideLength: Double, name: String) {
        
        self.sideLength = sideLength;
        super.init(name: name)
        numberOfSides = 4
    }
}

/// 计算属性setter和getter
class Circle {

    var area: Double = 0.0
    var r: Double {
    
        set {
        
            area = newValue * newValue * 3.1415926
        }
        
        get {
        
            return sqrt(area/3.1415926)
        }
    }
    
}

/// 检测属性willSet和didSet
class People: NSObject {

    var age: Int = 0 {
    
        willSet {
            
            // 我们需要在Age属性变化后，做一些事情
            print("will set an new value \(newValue) to age")
        }
        
        didSet {
        
            // 我们需要在age属性发生变化后，做一些事情
            print("did set change from value \(oldValue) to \(age)")

        }
    }
}

var me = People()
me.age = 20;


/// 添加协议
protocol LoveMusic {

    func songMusic()
}

protocol Draw {

    func draw()
}

class Student: LoveMusic, Draw {

    var name = "小明"
    
    func songMusic() {
        
        print("会唱歌")

    }
    
    func draw() {
        
        print("会画画")
    }
}

var xiaoming = Student()
xiaoming.songMusic();
xiaoming.draw()


/// 定义父类
class Person {

    var name: String
    var rename: String {
    
        return self.name
    }
    
    init(_ name: String) {
        
        self.name = name
    }
    
    func describe() -> String {
        
        return self.name
    }
    
    class func describeClass() -> String {
    
        return "这是一个描述人的类"
    }
    
}


/// 重写
class Man: Person {

    var score: Double
    override var rename: String {
    
        set {
        
            self.name = newValue
        }
        
        get {
        
            return self.name;
        }
    }
    
    override init (_ name:String) {
    
        self.score = 0.0;
        super.init(name)
    }
    
    override func describe() -> String {
        
        return self.name + "\(self.score)"
    }
    
    override class func describeClass() -> String {
    
        return "我是描述男人的类"
    }
}

var xiaoli = Man("小李");

xiaoli.name

xiaoli.rename = "xiaoli"

xiaoli.name

xiaoli.describe()

Man.describeClass()

/*
重写计算属性的时候,只能增加功能,不能减少功能,比如父类的计算属性为(set get) 重写的话,只能全部重写,但是如果父类只有get方法,可以给子类增加set功能
重写监测属性,不能有初始化的值

*/


/// is 的使用
class Teacher: Person {

    var tearchName: String
    init(name: String) {
        
        self.tearchName = name;
        super.init(name)
    }
}

let teacher = Teacher.init(name: "酷走天涯")
var persons:[Any] = []
persons.append(teacher)

for person in persons {
    
    if person is Teacher {
        
        print("我是Teacher")
    }
    
    if person is Person {
        
        print("我是Person")
    }
}

/// as? 的使用
for person in persons {
    
    if let p = person as? Teacher {
        
        print("我是Teacher")
    }
    
    if let p = person as? Person {
        
        print("我是Person")
    }
}

/// as! 的使用 一旦teacher 不是Person 类型或者它的子类,系统就会报错
let tearcher1: Any = Teacher.init(name: "库走天涯")
let p = tearcher1 as! Person



/// 其他情况
var things:[Any] = [];

for thing in things {
    switch thing {
    case 0 as Int:  // 如果值等于0 请检测是不是Int
        print("zero as an Int")
    case 0 as Double:// 和上面类型
        print("zero as a Double")
    case let someInt as Int: // 模式匹配上面的值,检测是不是Int
        print("an integer value of \(someInt)")
    case let someDouble as Double where someDouble > 0:// 模式匹配上面的值 检测是不是double 并且判断它是不是大于0
        print("a positive double value of \(someDouble)")
    case is Double: // 检测是不是double类型
        print("some other double value that I don't want to print")
    case let someString as String: // 模式匹配是不是String类型
        print("a string value of \"\(someString)\"")
    case let (x, y) as (Double, Double): // 模式匹配是不是元组类型,并且检测数据类型
        print("an (x, y) point at \(x), \(y)")
    case let movie as Person:
        print("a movie called \(movie.name), dir. \(movie.rename)")
    case let stringConverter as  (String) -> String:
        print(stringConverter("Michael"))
    default:
        print("something else")
    }
}

/*
 
初始化顺序

1.首先在自己的初始化方法中先给自己的属性初始化
2.然后调用父类的初始化
3.最后修改父类的属性
 
*/






